package main;

import indexes.BattingIndex;
import indexes.PlayerIDIndex;
import indexes.PlayerNameIndex;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import util.BattingDatabaseFile;
import util.DatabaseFile;
import util.PlayerLogger;

import commands.CommandFileParser;

/**
 * This is the driver class that runs the player database.
 * Two indexes are maintained - one that links a player's id
 * to a file offset, and one that links a player's name to
 * one or more offest.  Each index is supported by an AVL tree.
 * @author bfults (Brian Fults - 905084698)
 *
 */
public class PlayerDB
{

    /**
     * 
     * @param args args contains 3 things:
     * a db file name, a command script file name,
     * and a log file name.
     */
    public static void main(String[] args)
    {
        //Begin initialization
        //Easiest case is that we don't run at all.
        if (args.length < 5)
        {
            System.out.println("Log file name required.");
            System.exit(0);
        }
        PlayerLogger logger = null;
        try
        {
            logger = new PlayerLogger(args[4]);
        }
        catch (IOException e)
        {
            System.out.println("Error generating logger with name: " +
                args[4] + " and error message:\n" + e.getMessage());
            System.exit(0);
        }
        
        
        CommandFileParser parser = null;
               
        //Next, make sure we have a file for the command script.
        try
        {
            parser = new CommandFileParser(
                new File(args[3]));
        }
        catch (FileNotFoundException e)
        {
            System.out.println("Command script not found.  Please check" +
                " your spelling and try again.");
            try
            {
                logger.close();
            }
            catch(IOException e1)
            {
                System.out.println("Error closing constructed logger:\n" + e1.getMessage());
            }
            System.exit(0);
        }
        BattingDatabaseFile battingDatabase = null;
        try
        {
            battingDatabase = new BattingDatabaseFile(args[2]);
        }
        catch ( FileNotFoundException e )
        {
            System.out.println("Error generating batting database file with name: " +
                args[2] + " and error message:\n" + e.getMessage());
            try
            {
                logger.close();
                parser.close();
            }
            catch(IOException e1)
            {
                System.out.println("Error closing files: " + e1.getMessage());
            }
            System.exit(0);
        }
        
        //Having succeeded in the first two endeavors, we are ready to go.
        DatabaseFile database = null;
        try
        {
             database = new DatabaseFile(args[1]);
        }
        catch ( FileNotFoundException e )
        {
            System.out.println("Error generating database file with name: " +
                args[1] + " and error message:\n" + e.getMessage());
            try
            {
                logger.close();
                parser.close();
                battingDatabase.close();
            }
            catch(IOException e1)
            {
                System.out.println("Error closing files: " + e1.getMessage());
            }
            System.exit(0);
        }
        int m = -1;
        try
        {
           m = Integer.parseInt(args[0]); 
        }
        catch (NumberFormatException e)
        {
            System.out.println("Parsing error encountered while trying to get m: " + e.getMessage());
            System.out.println("Closing files.");
            try
            {
                logger.close();
                parser.close();
                battingDatabase.close();
                database.close();
            }
            catch(IOException e1)
            {
                System.out.println("Error closing files: " + e1.getMessage());
            }
            System.exit(0);
        }
        //end initialization
        
        //Begin actual execution
        PlayerIDIndex idIndex = new PlayerIDIndex(logger);
        PlayerNameIndex nameIndex = new PlayerNameIndex(logger);
        BattingIndex battingIndex = null;
        try
        {
            battingIndex = new BattingIndex(logger, m);
        }
        catch (IOException e)
        {
            System.out.println("Error creating batting index from log file: " + e.getMessage());
            try
            {
                logger.close();
                parser.close();
                battingDatabase.close();
                database.close();
            }
            catch(IOException e1)
            {
                System.out.println("Error closing files: " + e1.getMessage());
            }
        }
        
        boolean keepWorking = true;
        
        try
        {
            while (parser.hasMoreCommands() && keepWorking)
            {
                keepWorking = parser.nextCommand().execute( idIndex, nameIndex, logger, database, battingIndex, battingDatabase);
            }
        }
        catch(IOException e)
        {
            try
            {
                logger.write("Error executing command:\n" + e.getMessage() + "\n");
            }
            catch(IOException e1)
            {
                System.out.println("Error executing command:\n" +
                    e.getMessage() + "\nAdditionally, error writing to" +
                    		"log file:\n" + e1.getMessage());
            }
        }
        //End actual execution
        
        //Close files
        try
        {
            logger.write( "Exiting program\n" );
            parser.close();
            logger.write("Command parser closed\n");
            database.close();
            logger.write("Database closed\n");
            battingDatabase.close();
            logger.write("Batting database closed.\n");
            logger.write("Closing logger\n");
            logger.close();
        }
        catch ( IOException e )
        {
            System.out.println("Error closing files:\n" + e.getMessage());
        }
        
        System.exit(0);
        
    }
}
